
// import { ColumnProps } from './../testData'
import { arrToObj, objToArr } from '../helper'
import { createStore, Commit } from 'vuex'
import axios, { AxiosRequestConfig } from 'axios' // 这个类型包括了请求的方法。

export interface ResponseType<P={}>{
  code: number;
  msg: string;
  data: P;// 这个数据可能是照片格式的也可能是其它文件类型的
}// 这个是为了能够规范返回数据的一个格式，这个泛型如何去应用的值得再次回顾。？
export interface UserProps{
  isLogin: boolean;
  nickName?: string;
  _id?: string;
  column?: string;
  email?: string;
  avatar?: ImageProps;
  description?: string;

}
export interface ImageProps{
  _id?: string;
  url?: string;
  createdAt?: string;
  fitUrl?: string;
}
export interface GlobalErrorProps {// 全局错误状态类型
  message?: string;
  status: boolean;
}
export interface PostProps {
  _id?: string;
  title?: string;
  content?: string;
  excerpt?: string;
  image?: ImageProps | string; // 为何
  createdAt?: string;
  avatar?: ImageProps;
  column?: string;
  author?: string | UserProps;
}// 文章的接口
interface ListProps <P> {
  [id: string]: P;

}
export interface GlobalDataProps{
  error: GlobalErrorProps;
  loading: boolean;
  columns: ListProps<ColumnProps>;
  posts: ListProps<PostProps>;
  user: UserProps;
  token: string;
}// store的全局类型。
export interface ColumnProps {
  _id?: string;
  title: string;
  avatar?: ImageProps;
  description: string;
}

const getAndCommit = async (url: string, mutationame: string, commit: Commit) => {
  const { data } = await axios.get(url)
  commit(mutationame, data)
  return data// 这里犯了大错，没有返回这个函数的结果，导致通过这个函数获取的data，始终拿不到。
}
const postAndCommit = async (url: string, mutationame: string, commit: Commit, payload: any) => {
  const { data } = await axios.post(url, payload)

  commit(mutationame, data)
  return data
}
const asyncAndCommit = async (url: string, mutationame: string, commit: Commit, config: AxiosRequestConfig) => {
  const { data } = await axios(url, config)// 这里是把这个axios直接当一个函数，里面可以直接传递这个方法作为参数。
  commit(mutationame, data)// 触发mutation
  return data
}

const store = createStore<GlobalDataProps>({
  state: {
    error: { status: false }, // 全局错误的状态，默认值就是false
    token: localStorage.getItem('token') || '', // 这里我犯错误了就是自己没有从localstorage里去获取我想要的值，你如果不加的话不就又为空了吗，每次都去刷新时store也变为初始值了
    columns: {},
    posts: {}, // 整个文章列表信息
    user: { isLogin: false }, // 用户登录信息
    loading: false// 全局loading特效是否存在
  },
  mutations: {
    // login (state) {
    //   state.user = { ...state.user, isLogin: true, name: 'scx' }
    // },
    updatePost (state, { data }) {
      state.posts[data._id] = data
      // state.posts = state.posts.map(post => { // state.post是整个文章列表信息，所以需要
      //   console.log(post)
      //   if (post._id === data._id) { // 这里相当于做了一个权限，就是你更新的文章的所返回的id号，必须和你当前post文章的id号是一致的，一致才能修改数据，不一致，就不会去修改。
      //     return data
      //   } else {
      //     return post
      //   }
      // })// 这里的逻辑就是如果修改文章的id号和你的跟新文章的id号一致的情况下，这个文章的信息才可以去跟新。
    },
    createPost (state, newpost) {
      state.posts[newpost._id] = newpost // 此时已经成为了一个对象
    },
    deletePost (state, { data }) {
      delete state.posts[data.id] // 就是过滤到和你删除的那个文章号的id,之后通过hash表的查找，直接定位到需要删除的文章
    }, // 删除文章的mutations
    fetchColumns (state, rawData) {
      state.columns = arrToObj(rawData.data.list)// list是一个数组需要将其转换为对象
    },
    fetchColumn (state, rawData) {
      state.columns[rawData.data._id] = rawData.data
    },
    fetchPosts (state, rawData) {
      state.posts = arrToObj(rawData.data.list)
    },
    fetchPost (state, rawData) {
      state.posts[rawData.data._id] = rawData.data
    },
    setError (state, e: GlobalErrorProps) {
      state.error = e
    }, // 这里是去触发这个函数并传递这个错误状态以及信息，然后在相应的组件上去，去显示这个状态。
    setLoading (state, status) {
      state.loading = status
    },
    fetchCurrentUser (state, rawData) {
      state.user = { isLogin: true, ...rawData.data }// 这个是个大坑，就是以后再拿这个后端数据的时候记得去，看一下这个后端数据的格式，每个接口定义返回的结构都不太一样。
    },
    Logins (state, rawdata) {
      const { token } = rawdata.data
      state.token = token
      localStorage.setItem('token', token)// 就是在你登录的时候去将这个信息存储到浏览器里。
      axios.defaults.headers.common.Authorization = `Bearer ${token}`// 就是你每次登录的时候,只要是axios的请求都可以将这个带上，都要带上这个token进行鉴权。
    },
    logout (state) {
      state.token = ''
      localStorage.removeItem('token')// 删除本地浏览器里的token字段
      delete axios.defaults.headers.common.Authorization// 由于我并不想继续保持登录状态，就不必再去鉴权了，所以我需要去删掉。
    } // 退出登录的逻辑你想，这里就是说这个，
  },
  actions: {
    updatePost ({ commit }, { id, payload }) { // payload就是你需要去更新的数据
      return asyncAndCommit(`/posts/${id}`, 'updatePost', commit, { method: 'patch', data: payload })
    },
    fetchColumns ({ commit }) {
      return getAndCommit('/columns', 'fetchColumns', commit)
      // 这里通过异步的请求来获取所有的文章专栏
    },
    deletePost ({ commit }, id) { // payload就是你需要去更新的数据
      return asyncAndCommit(`/posts/${id}`, 'deletePost', commit, { method: 'delete' })
    }, // 删除文章触发的action
    fetchColumn ({ commit }, cid) { // 找到对应id号的专栏详情
      return getAndCommit(`/columns/${cid}`, 'fetchColumn', commit)
    },
    createPost ({ commit }, payload) {
      return postAndCommit('/posts', 'createPost', commit, payload)
    },

    fetchPosts ({ commit }, cid) { // 找到对应id号专栏下的所有文章
      return getAndCommit(`/columns/${cid}/posts`, 'fetchPosts', commit)
    },

    fetchCurrentUser ({ commit }) {
      return getAndCommit('/user/current', 'fetchCurrentUser', commit)
    },

    loginandfetch ({ dispatch }, logindata) {
      return dispatch('Logins', logindata).then(() => {
        return dispatch('fetchCurrentUser')
      })// 这里的逻辑就是说这个先进行登录，设置头字段，然后再去更新当前全局状态里的state里的用户信息
    },
    Logins ({ commit }, payload) {
      return postAndCommit('/user/login', 'Logins', commit, payload)
    },
    fetchPost ({ commit }, id) {
      return getAndCommit(`/posts/${id}`, 'fetchPost', commit)
    }// 这个是用来获取文章详情的一个action

  },
  getters: {
    getColumns: (state) => {
      return objToArr(state.columns)
    },
    getColumnByid: (state) => (id: string) => {
      return state.columns[id]
    }, // 优化后直接就去用这个id号
    getPostsBycid: (state) => (CID: string) => {
      return objToArr(state.posts).filter(post => post.column === CID)
    }, // getter为什么不是一个函数。
    getCurrent: (state) => (id: string) => {
      return state.posts[id]
    }
  }// 就是找这个当前用户的id号和这个文章详情接口的id号是否一致，一致就直接返回了
})
export default store
